package com.ktgj.pay.phoneSound;

import java.io.BufferedInputStream;
import java.io.BufferedOutputStream;
import java.net.HttpURLConnection;
import java.net.URL;
import java.util.Date;

import com.ktgj.pay.utils.LogLevel;
import com.ktgj.pay.utils.SslConnection;
import com.ktgj.pay.utils.Toolkit;

public class TransactionClientInternal {

	public TransactionClientInternal(String url) {
		this.url = url;
	}

	private String merchantNo="";
	private String terminalNo="";
	private String merchantPwd="";
	private String url="";
	private int timeout = 120000;
	private String ServerCert;
	private int contentLength=9;

	public void setMerchantNo(String merchantNo) {
		this.merchantNo = merchantNo;
	}

	public String getMerchantNo() {
		return merchantNo;
	}

	public void setTerminalNo(String terminalNo) {
		this.terminalNo = terminalNo;
	}

	public void setMerchantPwd(String merchantPwd) {
		this.merchantPwd = merchantPwd;
	}

	public String getTerminalNo() {
		return terminalNo;
	}

	public String getMerchantPwd() {
		return merchantPwd;
	}

	private String getServerCert() {
		return ServerCert;
	}

	public void setServerCert(String serverCert) {
		ServerCert = serverCert;
	}

	public SimpleXml connectionTest(String acqSsn, String encryptKey) throws Exception{
		SimpleXmlImpl request = new SimpleXmlImpl();
		request.setVersion("2.1.0");
		request.setProcCode("0800");
		request.setAcqSsn(acqSsn);
		request.setTransDatetime(Toolkit.yyyyMMddHHmmss(new Date()));
		request.setMerchantNo(merchantNo);
		request.setTerminalNo(terminalNo);
		return transact(request, encryptKey);
	}

	public SimpleXml C2CStoreAccount(String acqSsn, String mobileNo,String name, String idCardNo, String idCardValidTime,
			String idCardExpireTime, String idCardAddres, String idCardPhotoPath, String currentPhotoPath,
			String receiverName, String receiverContry, String receiverAddress,	String receiverBankContry, String receiverBankCity,
			String receiverBankAddress, String receiverBankSwift, String receiverAccountNo, String contractPath, String orderNo, 
			String purpose, String remark, String encryptKey) throws Exception{
		C2CXmlImpl xml = new C2CXmlImpl();
		xml.setVersion("2.1.1");
		xml.setProcCode("0600");
		xml.setProcessCode("600002");
		xml.setAcqSsn(acqSsn);
		xml.setTransDatetime(Toolkit.yyyyMMddHHmmss(new Date()));
		xml.setMobile(mobileNo);
		xml.setName(name);
		xml.setIDCardNo(idCardNo);
		xml.setIDCardValidTime(idCardValidTime);
		xml.setIDCardExpireTime(idCardExpireTime);
		xml.setIDCardAddress(idCardAddres);
		xml.setIDCardPhotoPath(idCardPhotoPath);
		xml.setCurrentPhotoPath(currentPhotoPath);
		xml.setReceiverName(receiverName);
		xml.setReceiverContry(receiverContry);
		xml.setReceiverAddress(receiverAddress);
		xml.setReceiverBankContry(receiverBankContry);
		xml.setReceiverBankCity(receiverBankCity);
		xml.setReceiverBankAddress(receiverBankAddress);
		xml.setReceiverBankSwift(receiverBankSwift);
		xml.setReceiverAccountNo(receiverAccountNo);
		xml.setContractPath(contractPath);
		xml.setMerchantNo(merchantNo);
		xml.setTerminalNo(terminalNo);
		MD5 md5 = new MD5();
		xml.setMAC(md5.getMD5ofStr(ApiV2Util.getMACString(xml) + " " + merchantPwd));
		C2CXmlImpl result = (C2CXmlImpl) transact(xml,encryptKey);
		if(result != null && !result.getMAC().equals(md5.getMD5ofStr(ApiV2Util.getMACString(result) + " " + merchantPwd))){
			throw new Exception("У��MACʧ��");
		}
		return result;
	}
	
	public SimpleXml C2CStoreAccountStep1(String acqSsn, String mobileNo,String name, String idCardNo, String idCardValidTime,
			String idCardExpireTime, String idCardAddres, String idCardPhotoPath, String currentPhotoPath, String encryptKey) throws Exception{
		
		return C2CStoreAccount(acqSsn, mobileNo, name, idCardNo, idCardValidTime, idCardExpireTime, 
				idCardAddres, idCardPhotoPath, currentPhotoPath, "", "", "", "", "", "", "", "", "","","","", encryptKey);
	}
	
	public SimpleXml C2CStoreAccountStep2(String acqSsn, String mobileNo, String receiverName, String receiverContry, String receiverAddress, String receiverBank,
			String receiverBankContry, String receiverBankCity,String receiverBankAddress, String receiverBankSwift, String receiverAccountNo, String encryptKey) throws Exception{
		return C2CStoreAccount(acqSsn, mobileNo, "", "", "", "", "", "", "", 
				receiverName, receiverContry, receiverAddress, receiverBankContry, receiverBankCity, receiverBankAddress, 
				receiverBankSwift, receiverAccountNo, "","","","", encryptKey);
	}
	
	public SimpleXml C2CStoreAccountStep3(String acqSsn, String mobileNo, String contractPath, String orderNo, String purpose, String remark, String encryptKey) throws Exception{
		return C2CStoreAccount(acqSsn, mobileNo, "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", contractPath, orderNo, purpose, remark, encryptKey);
	}

	public SimpleXml C2CQueryAccount(String acqSsn, String mobileNo,String encryptKey) throws Exception {
		C2CXmlImpl xml = new C2CXmlImpl();
		xml.setVersion("2.1.1");
		xml.setProcCode("0600");
		xml.setProcessCode("600001");
		xml.setAcqSsn(acqSsn);
		xml.setTransDatetime(Toolkit.yyyyMMddHHmmss(new Date()));
		xml.setMobile(mobileNo);
		xml.setMerchantNo(merchantNo);
		xml.setTerminalNo(terminalNo);
		MD5 md5 = new MD5();
		xml.setMAC(md5.getMD5ofStr(ApiV2Util.getMACString(xml) + " " + merchantPwd));
		C2CXmlImpl result = (C2CXmlImpl) transact(xml,encryptKey);
		if(result != null && !result.getMAC().equals(md5.getMD5ofStr(ApiV2Util.getMACString(result) + " " + merchantPwd))){
			throw new Exception("У��MACʧ��");
		}
		return result;
	}

	public SimpleXml QueryCurrency(String acqSsn, String currency, String direction, String accountType, String queryDate, String encryptKey) throws Exception{
		CurrencyXmlImpl xml = new CurrencyXmlImpl();
		xml.setVersion("2.1.2");
		xml.setProcCode("0700");
		xml.setProcessCode("700000");
		xml.setAcqSsn(acqSsn);
		xml.setCurrency(currency);
		xml.setDirection(direction);
		xml.setAccountType(accountType);
		xml.setQueryDate(queryDate);
		xml.setTransDatetime(Toolkit.yyyyMMddHHmmss(new Date()));
		xml.setMerchantNo(merchantNo);
		xml.setTerminalNo(terminalNo);
		MD5 md5 = new MD5();
		xml.setMAC(md5.getMD5ofStr(ApiV2Util.getMACString(xml) + " " + merchantPwd));
		CurrencyXmlImpl result = (CurrencyXmlImpl) transact(xml,encryptKey);
		if(result != null && !result.getMAC().equals(md5.getMD5ofStr(ApiV2Util.getMACString(result) + " " + merchantPwd))){
			throw new Exception("У��MACʧ��");
		}
		return result;
	}

	public SimpleXml QueryExternalBind(String acqSsn, String mobileNo, String openId, String bindIdType, String encryptKey) throws Exception {
		WebCatXmlImpl xml = new WebCatXmlImpl();
		xml.setVersion("2.1.4");
		xml.setProcCode("0900");
		xml.setProcessCode("900000");
		xml.setAcqSsn(acqSsn);
		xml.setTransDatetime(Toolkit.yyyyMMddHHmmss(new Date()));
		xml.setBindIDType(bindIdType);
		xml.setOpenId(openId);
		xml.setMobileNo(mobileNo);
		xml.setMerchantNo(merchantNo);
		
		MD5 md5 = new MD5();
		xml.setMAC(md5.getMD5ofStr(ApiV2Util.getMACString(xml) + " " + merchantPwd));
		WebCatXmlImpl result = (WebCatXmlImpl)transact(xml,encryptKey);
		
		if(result != null && !result.getMAC().equals(md5.getMD5ofStr(ApiV2Util.getMACString(result) + " " + merchantPwd))){
			throw new Exception("У��MACʧ��");
		}
		return result;
	}

	public SimpleXml BindExternalId(String acqSsn, String mobileNo, String openId, String bindIdType, String encryptKey) throws Exception{
		WebCatXmlImpl xml = new WebCatXmlImpl();
		xml.setVersion("2.1.4");
		xml.setProcCode("0900");
		xml.setProcessCode("900001");
		xml.setAcqSsn(acqSsn);
		xml.setTransDatetime(Toolkit.yyyyMMddHHmmss(new Date()));
		xml.setBindIDType(bindIdType);
		xml.setOpenId(openId);
		xml.setMobileNo(mobileNo);
		xml.setMerchantNo(merchantNo);
		
		MD5 md5 = new MD5();
		xml.setMAC(md5.getMD5ofStr(ApiV2Util.getMACString(xml) + " " + merchantPwd));
		WebCatXmlImpl result = (WebCatXmlImpl)transact(xml,encryptKey);
		
		if(result != null && !result.getMAC().equals(md5.getMD5ofStr(ApiV2Util.getMACString(result) + " " + merchantPwd))){
			throw new Exception("У��MACʧ��");
		}
		return result;
	}

	public SimpleXml SendSms(String acqSsn, String mobileNo, String encryptKey) throws Exception {
		WebCatXmlImpl xml = new WebCatXmlImpl();
		xml.setVersion("2.1.4");
		xml.setProcCode("0900");
		xml.setProcessCode("900002");
		xml.setAcqSsn(acqSsn);
		xml.setTransDatetime(Toolkit.yyyyMMddHHmmss(new Date()));
		xml.setMobileNo(mobileNo);
		xml.setMerchantNo(merchantNo);
		
		MD5 md5 = new MD5();
		xml.setMAC(md5.getMD5ofStr(ApiV2Util.getMACString(xml) + " " + merchantPwd));
		WebCatXmlImpl result = (WebCatXmlImpl)transact(xml,encryptKey);
		
		if(result != null && !result.getMAC().equals(md5.getMD5ofStr(ApiV2Util.getMACString(result) + " " + merchantPwd))){
			throw new Exception("У��MACʧ��");
		}
		return result;
	}

	public SimpleXml QueryOrderByMobileNo(String acqSsn, String mobileNo, String startTime, String endTime, String encryptKey) throws Exception {
		WebCatXmlImpl xml = new WebCatXmlImpl();
		xml.setVersion("2.1.4");
		xml.setProcCode("0900");
		xml.setProcessCode("900003");
		xml.setAcqSsn(acqSsn);
		xml.setTransDatetime(Toolkit.yyyyMMddHHmmss(new Date()));
		xml.setMobileNo(mobileNo);
		xml.setQueryStartTime(startTime);
		xml.setQueryEndTime(endTime);
		xml.setMerchantNo(merchantNo);
		
		MD5 md5 = new MD5();
		xml.setMAC(md5.getMD5ofStr(ApiV2Util.getMACString(xml) + " " + merchantPwd));
		WebCatXmlImpl result = (WebCatXmlImpl)transact(xml,encryptKey);
		
		if(result != null && !result.getMAC().equals(md5.getMD5ofStr(ApiV2Util.getMACString(result) + " " + merchantPwd))){
			throw new Exception("У��MACʧ��");
		}
		return result;
	}

	public SimpleXml UploadPhoto(String acqSsn, String mobileNo, String openId, String bindIdType, String orderNo, String notifyUrl, String photo, String encryptKey) throws Exception{
		WebCatXmlImpl xml = new WebCatXmlImpl();
		xml.setVersion("2.1.4");
		xml.setProcCode("0900");
		xml.setProcessCode("900004");
		xml.setAcqSsn(acqSsn);
		xml.setTransDatetime(Toolkit.yyyyMMddHHmmss(new Date()));
		xml.setMobileNo(mobileNo);
		xml.setOpenId(openId);
		xml.setBindIDType(bindIdType);
		xml.setNotifyUrl(notifyUrl);
		xml.setPhoto(photo);
		xml.setOrderNo(orderNo);
		xml.setMerchantNo(merchantNo);
		
		MD5 md5 = new MD5();
		xml.setMAC(md5.getMD5ofStr(ApiV2Util.getMACString(xml) + " " + merchantPwd));
		WebCatXmlImpl result = (WebCatXmlImpl)transact(xml,encryptKey);
		
		if(result != null && !result.getMAC().equals(md5.getMD5ofStr(ApiV2Util.getMACString(result) + " " + merchantPwd))){
			throw new Exception("У��MACʧ��");
		}
		return result;
	}

	public SimpleXml rescueOrder(String acqSsn, String accountNo, String mobileNo, String amount, String currency, 
			String merchantOrderNo, String description, String synAddress,String asynAddress, String merchantName, 
			String orderFrom, String language, String orderType, String reference, String idCardName, String idCardNo,
			String bankAddress, String idCardType, String beneficiaryName, String beneficiaryMobileNo, String deviceData,
			String deliveryAddress, String ipAddress, String location, String system3rdName, boolean mobileChecked,
			int merchantAccountLevel, int merchantAccountActivity, boolean vip, String transData, String userFlag,
			String encryptKey) throws Exception {
		
		RescueXmlImpl xml = new RescueXmlImpl();
		xml.setVersion("2.3.0");
		xml.setProcCode("0200");
		xml.setProcessCode("190010");
		xml.setAcqSsn(acqSsn);
		xml.setTransDatetime(Toolkit.yyyyMMddHHmmss(new Date()));
		xml.setMerchantNo(merchantNo);
		xml.setTerminalNo(terminalNo);
		xml.setAccountNo(accountNo);
		xml.setMobileNo(mobileNo);
		xml.setAmount(amount);
		xml.setCurrency("".equals(currency)?"CNY":currency);
		xml.setSynAddress(synAddress);
		xml.setAsynAddress(asynAddress);
		xml.setMerchantName(merchantName);
		xml.setMerchantOrderNo(merchantOrderNo);
		xml.setOrderFrom(orderFrom);
		xml.setLanguage(language);
		xml.setDescription(description);
		xml.setOrderType(orderType);
		xml.setReference(reference);
		xml.setIDCardName(idCardName);
		xml.setIDCardNo(idCardNo);
		xml.setBankAddress(bankAddress);
		xml.setIDCardType(idCardType);
		xml.setBeneficiaryName(beneficiaryName);
		xml.setBeneficiaryMobileNo(beneficiaryMobileNo);
		xml.setDeviceData(deviceData);
		xml.setDeliveryAddress(deliveryAddress);
		xml.setIpAddress(ipAddress);
		xml.setLocation(location);
		xml.setSystem3rdName(system3rdName);
		xml.setMobileChecked(mobileChecked?"1":"0");
		xml.setMerchantAccountLevel(merchantAccountLevel+"");
		xml.setMerchantAccountActivity(merchantAccountActivity+"");
		xml.setVIP(vip?"1":"0");
		xml.setTransData(transData);
		xml.setUserFlag(userFlag);

		MD5 md5 = new MD5();
		xml.setMAC(md5.getMD5ofStr(ApiV2Util.getMACString(xml) + " " + merchantPwd));
		RescueXmlImpl result = (RescueXmlImpl) transact(xml,encryptKey);
		if(result != null && !result.getMAC().equals(md5.getMD5ofStr(ApiV2Util.getMACString(result) + " " + merchantPwd))){
			throw new Exception("У��MACʧ��");
		}
		return result;
	}

	private SimpleXml transact(SimpleXml request,String encryptKey) throws Exception{
		try {
			Toolkit.writeLog(TransactionClientInternal.class.getName(), "transact.send", url + "|" + timeout + "|" + request.toString());
			HttpURLConnection connect = null;
			if (!url.contains("https:")) {
				URL urlConnect = new URL(url);
				connect = (HttpURLConnection) urlConnect.openConnection();
			} else {
				SslConnection urlConnect = new SslConnection();
				connect = (HttpURLConnection) urlConnect.openConnection(url);
			}

			connect.setReadTimeout(timeout);
			connect.setConnectTimeout(timeout);
			connect.setRequestMethod("POST");
			connect.setDoInput(true);
			connect.setDoOutput(true);
			connect.setRequestProperty("content-type", "text/html;charset=utf-8");

			String xml = request.toString();
			Toolkit.writeLog(TransactionClientInternal.class.getName(), "transact.xml\n", xml);
			RSAProvider rsa = new RSAProvider(Toolkit.getPropertyFromFile(Toolkit.GDYILIAN_CERT_METHOD));
			xml = rsa.sign(encryptKey, xml, this.getServerCert());
			xml = Toolkit.padLeft(xml.length() + "", contentLength) + xml;
            Toolkit.writeLog(TransactionClientInternal.class.getName(), "transact.sign", xml);

			connect.connect();
			BufferedOutputStream out = new BufferedOutputStream(connect.getOutputStream());

			out.write(xml.getBytes("UTF-8"));
			out.flush();
			out.close();

			BufferedInputStream in = new BufferedInputStream(connect.getInputStream());
			byte[] bts = new byte[10000000];
			int totalLen = 0, len = 0;
			while ((len = in.read(bts, totalLen, 1000)) != -1) {
				totalLen += len;
			}

			String result = Toolkit.toString(new String(bts, "UTF-8"));
            Toolkit.writeLog(TransactionClientInternal.class.getName(), "transact.result", result);
			result = rsa.verify(encryptKey, result.substring(contentLength));
            Toolkit.writeLog(TransactionClientInternal.class.getName(), "transact.verify", result);
			return ApiV2Util.toSimpleXml(result);
		} catch (Exception e) {
			Toolkit.writeLog(LogLevel.ERROR, TransactionClientInternal.class.getName(), e.getMessage());
			throw e;
		}
	}

}
